import data.Tuple;
import helper.Tools;

import java.util.List;
import java.util.ArrayList;

public class Openuncertainty 
{
	/**
	 * 
	 */
	public static double do_simulation(int n, double k, double pe, int times)
	{
		Tuple t1;
		Tuple t2;
		
		int count=0;
		for(int i=0;i<times;i++)
		{
			t1=new Tuple(n,k,pe,Tuple.OPEN);
			t2=new Tuple(n,k,pe,Tuple.OPEN);
			
			if(t1.is_order_changed(t2))
			{
				//System.out.println(t1);
				//System.out.println(t2);
				count++;
			}
		}
		
		return 1.0*count/times;
	}
	public static double do_deduction(double k, double pe)
	{
		double ph,pg;
		double change;
		
		if(k>=1.0)
		{
			ph=1.0/2.0-1.0/6.0/k;
			pg=1.0/2.0-1.0/6.0/k+1.0/48.0/k/k;
		}
		else if(0.5<=k && k<=1.0)
		{
			ph=-k*k/6.0+k/2.0;
			pg=0.5-1.0/6.0/k+1.0/48.0/k/k;
		}
		else if(0<=k && k<=0.5)
		{
			ph=-k*k/6.0+k/2.0;
			pg=-k*k/3.0+2.0*k/3.0;
		}
		else
		{
			ph=0;
			pg=0;
		}
		
		change=2*pe*(1-pe)*ph+pe*pe*pg;
		return change;
	}
	public static void do_simulation(String path, int times, int n_min, int n_max, int n_step, double pe_min, double pe_max, double pe_step, double k_min, double k_max, double k_step)
	{
		double p_simulation;
		double p_deduction;
		double absolute_error=0;
		double relative_error=0;
		double abs_err;
		double rel_err=0;
		int count=0;
		
		List<Object> head=new ArrayList<Object>();
		head.add("n");
		head.add("pe");
		head.add("k");
		head.add("relative error");
		
		List<List<Object>> data=new ArrayList<List<Object>>();
		
		for(int n=n_min;n<=n_max;n+=n_step)
		{
			for(double pe=pe_min;pe<=pe_max;pe+=pe_step)
			{
				for(double k=k_min;k<=k_max;k+=k_step)
				{
					p_simulation=Openuncertainty.do_simulation(n, k, pe, times);
					p_deduction=Openuncertainty.do_deduction(k, pe);
					abs_err=Math.abs(p_simulation-p_deduction);
					absolute_error+=abs_err;
					if(Math.abs(p_simulation-p_deduction)<0.000000001)
					{
						rel_err=Math.abs((p_simulation-p_deduction)/(p_simulation+0.000000001));
					}
					else
					{
						rel_err=Math.abs((p_simulation-p_deduction)/(p_simulation));
					}
					relative_error+=rel_err;
					count++;
					System.out.println("OPEN:n="+n+",pe="+pe+",k="+k+",simulation="+p_simulation+", deduction="+p_deduction+",absolute error="+Math.abs(p_simulation-p_deduction)+",relative error="+Math.abs((p_simulation-p_deduction)/(p_simulation+0.0000001)));	
					ArrayList<Object> list=new ArrayList<Object>();
					list.add(""+n);
					list.add(""+pe);
					list.add(""+k);
					list.add(""+rel_err);
					data.add(list);					
				}
			}
		}
		System.out.println("OPEN absolute error="+absolute_error/count+",relative error="+relative_error/count);
		Tools.create_4d_csv_data_file(head, data, path);
	}
	public static void main(String args[])
	{
		Openuncertainty.do_simulation("D:\\projects\\eclipse\\UncertaintyModel\\open.csv", 1000000, 10000, 100000, 10000, 0.0, 1.0, 0.1, 0.2, 2.0, 0.1);
	}
	
}
